﻿using System;
using System.Collections.Generic;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using Habanero.Base;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.Smooth;
using Habanero.Testability;
using NUnit.Framework;
using Rhino.Mocks;

namespace Firestarter.Test.Base.BusinessObjectMerger
{
    [TestFixture]
    public class TestMergeBOCompareBORels
    {

        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            ClassDef.ClassDefs.Clear();
            AllClassesAutoMapper.ClassDefCol = ClassDef.ClassDefs;
            ClassDefCol classDefCol = typeof(FakeMergeableParent).Assembly.MapClasses();
            ClassDef.ClassDefs.Add(classDefCol);
        }

        [SetUp]
        public virtual void SetupTest()
        {
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }


        [Test]
// ReSharper disable InconsistentNaming
        public void Test_CompareRelationships_WhenXRelationshipIsAssociation_Always_ReturnsTrue()
        {
            //---------------Set up test pack-------------------
            MergeBORelSpy<FakeBOWithOneToOneAssociationRel> mergeBO = new MergeBORelSpy<FakeBOWithOneToOneAssociationRel>();
            FakeBOWithOneToOneAssociationRel x = new FakeBOWithOneToOneAssociationRel();
            //---------------Assert Precondition----------------
            
            Assert.AreEqual(RelationshipType.Association, x.Relationships.GetSingle("FakeMergeableParentReverse").RelationshipDef.RelationshipType);
            
            //---------------Execute Test ----------------------
            //var result = mergeBO.CallCompareSingleRelationship(x.Relationships.GetSingle("FakeMergeableParentReverse"), y.Relationships.GetSingle("FakeMergeableParentReverse"));
            var result = mergeBO.CallCompareRelationships(x, null);
            //---------------Test Result -----------------------
            Assert.IsTrue(result);
        }
        /// <summary>
        /// Identical is defined as MergBO.CompareBusinessObjects returning true for the two BusinessObjects
        /// </summary>
        [Test]
        public void Test_CompareSingleRelationship_WhenRelationshipIsAggregationWithIdenticalChildObjects_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var testStringProp = GetRandomString();
            var childX = new FakeMergeableChild { TestStringProp = testStringProp };

            var childY = new FakeMergeableChild { TestStringProp = testStringProp };

            var relationshipX = CreateRelationship(childX);
            var relationshipY = CreateRelationship(childY);
            //---------------Assert Precondition----------------
            Assert.AreSame(childX, relationshipX.GetRelatedObject());
            Assert.AreSame(childY, relationshipY.GetRelatedObject());

            Assert.AreEqual(RelationshipType.Aggregation, relationshipX.RelationshipDef.RelationshipType);
            Assert.AreEqual(RelationshipType.Aggregation, relationshipY.RelationshipDef.RelationshipType);

            Assert.AreNotSame(childX, childY);
            AssertAreIdenticalMergeableBOs(childX, childY);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareSingleRelationship(relationshipX, relationshipY);
            //---------------Test Result -----------------------
           Assert.IsTrue(result);
        }

        [Test]
        public void Test_CompareSingleRelationship_WhenRelationshipIsAggregationTwoParentsWithDifferentChildObjects_ShouldReturnFalse()
        {
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var testStringProp = GetRandomString();
            var differentTestStringProp = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX = new FakeMergeableChild { TestStringProp = testStringProp };
            parentX.FakeMergeableChild = childX;

            var parentY = new FakeMergeableParent();
            var childY = new FakeMergeableChild { TestStringProp = differentTestStringProp };
            parentY.FakeMergeableChild = childY;


            var relationshipX = parentX.Relationships.GetSingle("FakeMergeableChild");
            var relationshipY = parentY.Relationships.GetSingle("FakeMergeableChild");
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            Assert.AreNotSame(parentX.FakeMergeableChild, parentY.FakeMergeableChild);


            Assert.AreSame(childX, relationshipX.GetRelatedObject());
            Assert.AreSame(childY, relationshipY.GetRelatedObject());

            Assert.AreEqual(RelationshipType.Aggregation, relationshipX.RelationshipDef.RelationshipType);
            Assert.AreEqual(RelationshipType.Aggregation, relationshipY.RelationshipDef.RelationshipType);

            Assert.AreNotSame(childX, childY);
            AssertAreNotIdenticalMergeableBOs(childX, childY);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareSingleRelationship(relationshipX, relationshipY);
            //---------------Test Result -----------------------
            Assert.IsFalse(result);
        }

        [Test]
        public void Test_CompareSingleRelationship_WhenRelationshipIsCompositionTwoParentsWithIdenticalChildObjects_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var testStringProp = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX = new FakeMergeableChild { TestStringProp = testStringProp };
            parentX.FakeMergeableCompositionChild = childX;

            var parentY = new FakeMergeableParent();
            var childY = new FakeMergeableChild { TestStringProp = testStringProp };
            parentY.FakeMergeableCompositionChild = childY;

            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            Assert.AreNotSame(parentX.FakeMergeableCompositionChild, parentY.FakeMergeableCompositionChild);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareSingleRelationship(parentX.Relationships.GetSingle("FakeMergeableCompositionChild"),
                                                               parentY.Relationships.GetSingle("FakeMergeableCompositionChild"));
            //---------------Test Result -----------------------
            Assert.IsTrue(result);
        }

        [Test]
        public void Test_CompareSingleRelationship_WhenRelationshipIsCompositionTwoParentsWithDifferentChildObjects_ShouldReturnFalse()
        {
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var testStringProp = GetRandomString();
            var differentTestStringProp = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX = new FakeMergeableChild { TestStringProp = testStringProp };
            parentX.FakeMergeableCompositionChild = childX;

            var parentY = new FakeMergeableParent();
            var childY = new FakeMergeableChild { TestStringProp = differentTestStringProp };
            parentY.FakeMergeableCompositionChild = childY;

            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            Assert.AreNotSame(parentX.FakeMergeableCompositionChild, parentY.FakeMergeableCompositionChild);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareSingleRelationship(parentX.Relationships.GetSingle("FakeMergeableCompositionChild"),
                                                               parentY.Relationships.GetSingle("FakeMergeableCompositionChild"));
            //---------------Test Result -----------------------
            Assert.IsFalse(result);
        }

        #region Added Tests for Aggregation
        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsAggregationTwoParentsEachWithOneIdenticalChildObject_ShouldReturnTrue()
        {   // Each parent with one children 
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var childStringProp = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp };
            parentX.FakeMergeables.Add(childX1);
          
            var parentY = new FakeMergeableParent();
            var childY1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childX1.TestStringProp };
            parentY.FakeMergeables.Add(childY1);

            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsTrue(result);
        }

        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsAggregationTwoParentsEachWithTwoIdenticalChildObject_ShouldReturnTrue()
        {   // Each parent with two children 
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var childStringProp= GetRandomString();
            var childStringProp2 = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp };
            var childX2 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp2 };
            parentX.FakeMergeables.Add(childX1);
            parentX.FakeMergeables.Add(childX2);

            var parentY = new FakeMergeableParent();
            var childY1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childX1.TestStringProp };
            var childY2 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childX2.TestStringProp };
            parentY.FakeMergeables.Add(childY1);
            parentY.FakeMergeables.Add(childY2);
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------

            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsTrue(result);
        }

        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsAggregationTwoParentsEachWithManyIdenticalChildObject_ShouldReturnTrue()
        {   // Each parent with many children 
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var childStringProp = GetRandomString();
            var childStringProp2 = GetRandomString();
            var childStringProp3 = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp };
            var childX2 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp2 };
            var childX3 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp3 };
            parentX.FakeMergeables.Add(childX1);
            parentX.FakeMergeables.Add(childX2);
            parentX.FakeMergeables.Add(childX3);

            var parentY = new FakeMergeableParent();
            var childY1 = childX1.Clone(); // new FakeMergeableChildWithToStringSameAsTestStringProp() { TestStringProp = childX1.TestStringProp };
            var childY2 = childX2.Clone(); // new FakeMergeableChildWithToStringSameAsTestStringProp() { TestStringProp = childX2.TestStringProp };
            var childY3 = childX3.Clone(); // new FakeMergeableChildWithToStringSameAsTestStringProp() { TestStringProp = childX3.TestStringProp };
            parentY.FakeMergeables.Add(childY1);
            parentY.FakeMergeables.Add(childY2);
            parentY.FakeMergeables.Add(childY3);
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------

            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsTrue(result);
        }

        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsAggregationTwoParentsEachWithOneDifferentChildObject_ShouldReturnFalse()
        {   // Each parent with one different child 

            // This test will not actually end up comparing the child nodes because the CompareMultipleRelationships method calls
            // CompareBoCol which in turn uses FindBusinessObject that uses a ToString() to find the object and as we are using the test prop 
            // as the return value for the ToString the matching business object will not be found and will CompareBusinessObjects will not be called.

            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var childStringProp = GetRandomString();
            var differentTestStringProp = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp };
            parentX.FakeMergeables.Add(childX);

            var parentY = new FakeMergeableParent();
            var childY = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = differentTestStringProp };
            parentY.FakeMergeables.Add(childY);
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsFalse(result);
        }

        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsAggregationTwoParentsEachWithOneDifferentChildObjectWithSameNameProp_ShouldReturnFalse()
        {   // Each parent with one different child 

            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            const string stdName = "stdName";
            var childStringProp = GetRandomString();
            var differentTestStringProp = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX = new FakeMergeableChildWithToStringOnNameProp { Name = stdName, TestStringProp = childStringProp };
            parentX.FakeMergeables.Add(childX);

            var parentY = new FakeMergeableParent();
            var childY = childX.Clone(); //new FakeMergeableChildWithToStringOnNameProp() { TestStringProp = differentTestStringProp };
            childY.TestStringProp = differentTestStringProp;
            parentY.FakeMergeables.Add(childY);
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsFalse(result);
        }

        #endregion

        #region Added Tests for Composition

        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsCompositionTwoParentsEachWithOneIdenticalChildObject_ShouldReturnTrue()
        {   // Each parent with one children 
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var childStringProp = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp };
            parentX.FakeCompositionMergeables.Add(childX1);

            var parentY = new FakeMergeableParent();
            var childY1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childX1.TestStringProp };
            parentY.FakeCompositionMergeables.Add(childY1);
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsTrue(result);
        }

        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsCompositionTwoParentsEachWithTwoIdenticalChildObject_ShouldReturnTrue()
        {   // Each parent with two children 
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var childStringProp = GetRandomString();
            var childStringProp2 = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp };
            var childX2 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp2 };
            parentX.FakeCompositionMergeables.Add(childX1);
            parentX.FakeCompositionMergeables.Add(childX2);
            parentX.Save();

            var parentY = new FakeMergeableParent();
            var childY1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childX1.TestStringProp };
            var childY2 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childX2.TestStringProp };
            parentY.FakeCompositionMergeables.Add(childY1);
            parentY.FakeCompositionMergeables.Add(childY2);
            parentY.Save();
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------

            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsTrue(result);
        }

        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsCompositionTwoParentsEachWithManyIdenticalChildObject_ShouldReturnTrue()
        {   // Each parent with many children 
            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            var childStringProp = GetRandomString();
            var childStringProp2 = GetRandomString();
            var childStringProp3 = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX1 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp };
            var childX2 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp2 };
            var childX3 = new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = childStringProp3 };
            parentX.FakeCompositionMergeables.Add(childX1);
            parentX.FakeCompositionMergeables.Add(childX2);
            parentX.FakeCompositionMergeables.Add(childX3);
            parentX.Save();

            var parentY = new FakeMergeableParent();
            var childY1 = childX1.Clone(); 
            var childY2 = childX2.Clone(); 
            var childY3 = childX3.Clone(); 
            parentY.FakeCompositionMergeables.Add(childY1);
            parentY.FakeCompositionMergeables.Add(childY2);
            parentY.FakeCompositionMergeables.Add(childY3);
            parentY.Save();
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------

            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsTrue(result);
        }

        [Test]
        public void Test_CompareMultipleRelationship_WhenRelationshipIsCompositionTwoParentsEachWithOneDifferentChildObjectWithSameNameProp_ShouldReturnFalse()
        {   // Each parent with one different child 

            //---------------Set up test pack-------------------
            var mergeBO = new MergeBORelSpy<FakeMergeableParent>();
            const string stdName = "stdName";
            var childStringProp = GetRandomString();
            var differentTestStringProp = GetRandomString();
            var parentX = new FakeMergeableParent();
            var childX = new FakeMergeableChildWithToStringOnNameProp { Name = stdName, TestStringProp = childStringProp };
            parentX.FakeCompositionMergeables.Add(childX);
            parentX.Save();

            var parentY = new FakeMergeableParent();
            var childY = childX.Clone(); 
            childY.TestStringProp = differentTestStringProp;
            parentY.FakeCompositionMergeables.Add(childY);
            parentY.Save();
            //---------------Assert Precondition----------------
            Assert.AreNotSame(parentX, parentY);
            //---------------Execute Test ----------------------
            var result = mergeBO.CallCompareMultipleRelationships(parentX.Relationships.GetMultiple("FakeMergeables"),
                                                               parentY.Relationships.GetMultiple("FakeMergeables"));
            //---------------Test Result -----------------------
            Assert.IsFalse(result);
        }

        private static ISingleRelationship CreateRelationship(FakeMergeableChild childX)
        {
            var relationshipX = GetSingleMergeableChildRelationship();
            relationshipX.SetRelatedObject(childX);
            return relationshipX;
        }

        #endregion

        private static ISingleRelationship GetSingleMergeableChildRelationship()
        {
            ISingleRelationship relationshipX = new SingleRelationshipStub<FakeMergeableChild>();
            relationshipX.RelationshipDef.RelationshipType = RelationshipType.Aggregation;
            return relationshipX;
        }

        private static string GetRandomString()
        {
            return RandomValueGen.GetRandomString();
        }

/*        private static IMergeBO GetMerger<T>() where T : class, IMergableBo
        {
            return MergeableBORegistry.Instance.Resolve<T>();
        }*/

        private static IMergeBO GetMerger(IClassDef classDef)
        {
            return MergeableBORegistry.Instance.Resolve(classDef.ClassType);
        }

        /// <summary>
        /// Identical is defined as MergBO.CompareBusinessObjects returning true for the two BusinessObjects
        /// </summary>
        private static void AssertAreIdenticalMergeableBOs(IMergableBo mergeableX, IMergableBo mergeableY)
        {
            var mergeBO = GetMerger(mergeableX.ClassDef);
            CompareResult result = mergeBO.CompareBusinessObjects(mergeableX, mergeableY);
            Assert.IsTrue(result.AreEqual, "The Mergeable BOs are not identical");
        }
        /// <summary>
        /// Identical is defined as MergBO.CompareBusinessObjects returning true for the two BusinessObjects
        /// </summary>
        private static void AssertAreNotIdenticalMergeableBOs(IMergableBo mergeableX, IMergableBo mergeableY)
        {
            var mergeBO = GetMerger(mergeableX.ClassDef);
            CompareResult result = mergeBO.CompareBusinessObjects(mergeableX, mergeableY);
            Assert.IsFalse(result.AreEqual, "The Mergeable BOs are identical but should not be");
        }
    }


    internal class MergeBORelSpy<T> : MergeBO<T> where T : class, IMergableBo
    {
        public bool CallCompareSingleRelationship(ISingleRelationship fromSingleRelationship, ISingleRelationship toSingleRelationship)
        {
            return CompareSingleRelationship(fromSingleRelationship, toSingleRelationship).AreEqual;

        }

        public bool CallCompareMultipleRelationships(IMultipleRelationship fromMultipleRelationship, IMultipleRelationship toMultipleRelationship)
        {
            return CompareMultipleRelationships(fromMultipleRelationship, toMultipleRelationship).AreEqual;
        }

        public bool CallCompareRelationships(T x, T y)
        {
            return CompareRelationships(x, y).AreEqual;
        }

/*        public IList<IBOError> CallCompareFailuresGetter()
        {
            return CompareFailures;
        }*/

    }


    internal class FakeMergeableChildWithToStringSameAsTestStringProp : FakeMergeableChild
    {
        public override string ToString()
        {
            return TestStringProp;
        }

        public FakeMergeableChildWithToStringSameAsTestStringProp Clone()
        {
            return new FakeMergeableChildWithToStringSameAsTestStringProp { TestStringProp = this.TestStringProp };
        }

    }


    internal class FakeMergeableChildWithToStringOnNameProp : FakeMergeableChild
    {
        public override string ToString()
        {
            return Name;
        }

        public string Name
        {
            get { return (string)GetPropertyValue("Name"); }
            set { SetPropertyValue("Name", value); }
        }

        public FakeMergeableChildWithToStringOnNameProp Clone()
        {
            return new FakeMergeableChildWithToStringOnNameProp { Name = this.Name, TestStringProp = this.TestStringProp };
        }

    }
    // ReSharper restore InconsistentNaming

    internal class SingleRelationshipStub<TBusinessObject> : SingleRelationship<TBusinessObject> where TBusinessObject : class, IBusinessObject, new()
    {
        private TBusinessObject _relatedObject;
        public SingleRelationshipStub() : base(MockRepository.GenerateStub<IBusinessObject>(), new SingleRelationshipDefStub<TBusinessObject>(), MockRepository.GenerateStub<IBOPropCol>() )
        {   
        }

        public override TBusinessObject GetRelatedObject()
        {
            return _relatedObject;
        }

        public override void SetRelatedObject(TBusinessObject relatedObject)
        {
            _relatedObject = relatedObject;
        }
    }
    internal class SingleRelationshipDefStub<TBusinessObject>: SingleRelationshipDef
    {
        public SingleRelationshipDefStub()
            : base(RandomValueGen.GetRandomString(), typeof(TBusinessObject), new RelKeyDef(), false, Habanero.Base.DeleteParentAction.Prevent)
        {
        }
    }
}